package com.uduemc.biso.node.web.api.controller;

import java.io.File;
import java.io.IOException;
import java.util.List;

import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.uduemc.biso.core.common.extities.CTemplateListData;
import com.uduemc.biso.core.common.extities.ctemplatelistdata.CTemplateItemData;
import com.uduemc.biso.core.extities.center.SysTemplateModel;
import com.uduemc.biso.core.extities.node.custom.LoginNode;
import com.uduemc.biso.core.utils.JsonResult;
import com.uduemc.biso.node.core.entities.SConfig;
import com.uduemc.biso.node.core.node.config.OperateLoggerStaticModel;
import com.uduemc.biso.node.core.node.config.OperateLoggerStaticModelAction;
import com.uduemc.biso.node.core.operate.entities.OperateLog;
import com.uduemc.biso.node.web.api.component.RequestHolder;
import com.uduemc.biso.node.web.api.component.TemplateAsync;
import com.uduemc.biso.node.web.api.service.CenterService;
import com.uduemc.biso.node.web.api.service.SConfigService;
import com.uduemc.biso.node.web.api.service.TemplateInitService;
import com.uduemc.biso.node.web.component.operate.OperateLoggerController;
import com.uduemc.biso.node.web.service.OperateLoggerService;

import cn.hutool.core.util.StrUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import lombok.extern.slf4j.Slf4j;

@RestController
@RequestMapping("/api/template")
@Slf4j
@Api(tags = "模板管理模块")
public class TemplateController {

	@Autowired
	private TemplateAsync templateAsync;

	@Autowired
	private RequestHolder requestHolder;

	@Autowired
	private SConfigService sConfigServiceImpl;

	@Autowired
	private CenterService centerServiceImpl;

	@Autowired
	private TemplateInitService templateInitServiceImpl;

	@Autowired
	private OperateLoggerService operateLoggerServiceImpl;

	/**
	 * 获取所有的 模板类型 数据
	 * 
	 * @return
	 */
	@PostMapping("/model-infos")
	public JsonResult modelInfos() {
		List<SysTemplateModel> allSysTemplateModel = centerServiceImpl.getAllSysTemplateModel();
		return JsonResult.ok(allSysTemplateModel);
	}

	@PostMapping("/infos")
	public JsonResult infos(@RequestParam("templatename") String templatename, @RequestParam("typeId") long typeId, @RequestParam("page") int page,
			@RequestParam(value = "size", required = false, defaultValue = "9") int size) {
		CTemplateListData cTemplateListData = centerServiceImpl.getCenterApiTemplateData(templatename, typeId, page, size);
		return JsonResult.ok(cTemplateListData);
	}

	@PostMapping("/init")
	public JsonResult init(@RequestParam("templateId") long templateId) throws Exception {
		// 获取对应的数据
		CTemplateItemData cTemplateItemData = centerServiceImpl.getCenterApiTemplateItemData(templateId);
		if (cTemplateItemData == null) {
			return JsonResult.illegal();
		}
		// 验证配置是否存在
		SConfig sConfig = sConfigServiceImpl.getInfoBySiteId(requestHolder.getHost().getId(), requestHolder.getCurrentSite().getId());
		if (sConfig == null) {
			return JsonResult.illegal();
		}

		Short status = sConfig.getStatus();
		if (status != null && status.shortValue() == (short) 2) {
			return JsonResult.messageWarning("正在初始化中，请稍后！");
		}

		// 首先得到 zipPath
		String zipPath = templateInitServiceImpl.zipPath(cTemplateItemData);
		if (StringUtils.isEmpty(zipPath)) {
			return JsonResult.assistance();
		}

		// copy 至对应的站点目录位置
		String copyAndUnzip = templateInitServiceImpl.copyAndUnzip(zipPath, requestHolder.getHost(), requestHolder.getCurrentSite().getId());
		if (StringUtils.isEmpty(copyAndUnzip)) {
			return JsonResult.assistance();
		}

		// 验证解压的验证文件是否正常
		// 生成验证文件
		File verificationFile = new File(copyAndUnzip + "/verification");
		if (!verificationFile.isFile()) {
			// 删除目录
			FileUtils.deleteDirectory(new File(new File(copyAndUnzip).getParentFile().toString()));
			return JsonResult.messageError("验证压缩文件失败！");
		}
		long sizeOfDirectory = FileUtils.sizeOfDirectory(new File(copyAndUnzip + "/data"));
		String verification = DigestUtils.md5DigestAsHex(String.valueOf(sizeOfDirectory).getBytes());
		String readFileToString = FileUtils.readFileToString(verificationFile, "UTF-8");
		if (!verification.equals(readFileToString)) {
			log.info("验证的密码：" + verification);
			log.info("验证文件内的密码：" + readFileToString);
			// 删除目录
			FileUtils.deleteDirectory(new File(new File(copyAndUnzip).getParentFile().toString()));
			return JsonResult.messageError("验证压缩文件失败！");
		}

		// 首先锁定host下的site站点
		sConfig.setStatus((short) 2);
		SConfig updateSConfig = sConfigServiceImpl.updateAllSiteConfig(sConfig);
		if (updateSConfig == null) {
			return JsonResult.assistance();
		}
		// 写入正在执行的日志
		OperateLog insert = initLog(cTemplateItemData.getTemplateName(), String.valueOf(templateId));
		if (insert == null) {
			return JsonResult.assistance();
		}
		// 变更site_config的状态，然后异步开始进行初始化操作
		templateAsync.initTemplate(requestHolder.getHost().getId(), requestHolder.getCurrentSite().getId(), copyAndUnzip, cTemplateItemData, insert);

		return JsonResult.messageSuccess("当前语点正在初始化！", updateSConfig);
	}

	protected OperateLog initLog(String templateName, String param) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {

		String declaringTypeName = "com.uduemc.biso.node.web.api.controller.ActionController";
		String modelName = OperateLoggerStaticModel.findModelName(declaringTypeName);
		String modelAction = OperateLoggerStaticModel.findModelAction(declaringTypeName, OperateLoggerStaticModelAction.UPDATE_THEMPLATE);
		String content = "选择官方模板（" + templateName + "）覆盖语点数据";
		short status = 2;

		Long hostId = requestHolder.getHost().getId();
		Long siteId = requestHolder.getCurrentSite().getId();
		Integer languageId = requestHolder.getCurrentSite().getLanguageId();
		LoginNode loginNode = requestHolder.getCurrentLoginNode();
		Long loginUserId = loginNode.getLoginUserId();
		String loginUserType = loginNode.getLoginUserType();
		String loginUserName = loginNode.getLoginUserName();
		String ipAddress = OperateLoggerController.ipAddress(requestHolder.getCurrentRequest());

		OperateLog operateLog = new OperateLog();
		operateLog.setHostId(hostId).setSiteId(siteId).setLanguageId(languageId).setUserId(loginUserId).setUserType(loginUserType).setUsername(loginUserName)
				.setModelName(modelName).setModelAction(modelAction).setContent(content).setParam(param).setReturnValue("").setOperateItem("").setStatus(status)
				.setIpaddress(ipAddress);

		OperateLog insert = operateLoggerServiceImpl.insert(operateLog);
		return insert;
	}

	@ApiOperation(value = "增加模板反馈信息", notes = "通过参数对模板反馈信息写入主控端数据库中，其中industry、referenceLink为必填项，其他字段非必填。")
	@ApiImplicitParams({ @ApiImplicitParam(name = "name", value = "客户称呼"), @ApiImplicitParam(name = "contactInformation", value = "联系方式"),
			@ApiImplicitParam(name = "industry", value = "客户行业", required = true), @ApiImplicitParam(name = "referenceLink", value = "参考地址", required = true),
			@ApiImplicitParam(name = "content", value = "反馈内容") })
	@PostMapping("/append-suggestion")
	@ApiResponses({ @ApiResponse(code = 200, message = "data 为 1，写入成功。") })
	public JsonResult appendSuggestion(@RequestParam(value = "name", required = false, defaultValue = "") String name,
			@RequestParam(value = "contactInformation", required = false, defaultValue = "") String contactInformation,
			@RequestParam("industry") String industry, @RequestParam("referenceLink") String referenceLink,
			@RequestParam(value = "content", required = false, defaultValue = "") String content) throws IOException {

		industry = StrUtil.trim(industry);
		referenceLink = StrUtil.trim(referenceLink);

		if (StrUtil.isBlank(industry) || StrUtil.isBlank(referenceLink)) {
			return JsonResult.messageError("industry、referenceLink 不能为空！");
		}

		if (StrUtil.length(industry) > 511) {
			return JsonResult.messageError("industry 字段长度不能超过511！industry:" + industry);
		}

		if (StrUtil.length(referenceLink) > 2040) {
			return JsonResult.messageError("referenceLink 字段长度不能超过2040！industry:" + referenceLink);
		}

		name = StrUtil.isBlank(StrUtil.trim(name)) ? "" : StrUtil.trim(name);
		if (StrUtil.length(name) > 511) {
			return JsonResult.messageError("name 字段长度不能超过511！name:" + name);
		}

		contactInformation = StrUtil.isBlank(StrUtil.trim(contactInformation)) ? "" : StrUtil.trim(contactInformation);
		if (StrUtil.length(contactInformation) > 2040) {
			return JsonResult.messageError("contactInformation 字段长度不能超过2040！contactInformation:" + contactInformation);
		}

		boolean bool = centerServiceImpl.appendTemplateSuggestion(name, contactInformation, industry, referenceLink, content);
		if (!bool) {
			return JsonResult.assistance();
		}
		return JsonResult.messageSuccess("感谢您的反馈！", 1);
	}
}
